﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;

namespace ajayumi.develop.CSharp.Core.Web
{
    public class SqlInjectionHttpModule : System.Web.IHttpModule
    {
        #region IHttpModule 成员
        public void Init(System.Web.HttpApplication context)
        {
            // TODO:  添加 HttpModule.Init 实现          
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }
        public void Dispose()
        {
            // TODO:  添加 HttpModule.Dispose 实现     
        }
        #endregion
        void context_BeginRequest(object sender, EventArgs e)
        {
            try
            {
                string str = "";
                string url = "/error.aspx?err=606";
                if (!HttpContext.Current.Request.Path.ToLower().EndsWith("/error.aspx"))
                {
                    if (HttpContext.Current.Request.QueryString != null)
                    {
                        for (int i = 0; i < HttpContext.Current.Request.QueryString.Count; i++)
                        {
                            str = HttpContext.Current.Request.QueryString.Keys[i];
                            if (!ProcessSqlQueryStrInjection(HttpContext.Current.Request.QueryString[str]))
                            {
                                HttpContext.Current.Response.Redirect(url);
                                HttpContext.Current.Response.End();
                            }
                        } for (int i = 0; i < HttpContext.Current.Request.Form.Count; i++)
                        {
                            str = HttpContext.Current.Request.Form.Keys[i];
                            if (!ProcessSqlFormStringInjection(HttpContext.Current.Request.Form[str]))
                            {
                                HttpContext.Current.Response.Redirect(url);
                                HttpContext.Current.Response.End();
                            }
                        }
                    }
                }
            }
            catch
            {
            }
        }        //sql get 方式注入过滤     
        private bool ProcessSqlQueryStrInjection(string queryString)
        {
            try
            {
                if (queryString.Trim() == "")
                {
                    return true;
                }
                string[] strInjectionArray = {@"([\s]+and[\s]+|[\s]+and\(|\)and[\s]+|\)and\()",     
                                              @"([\s]+or[\s]+|[\s]+or\(|\)or[\s]+|\)or\()",     
                                              @"(exec[\s]+(@|sp_executesql)|exec\(|execute[\s]+(@|sp_executesql)|execute\()",   
                                              @"sp_executesql[\s]+[N]{0,1}'",                     
                                              @"(;[\s]*\-\-|'[\s]*\-\-|\)[\s]*\-\-|'[\s]*;)",      
                                              @"declare[\s]+@",                                     
                                              @"(set[\s]+@|[\s]+set[\s]+)",         
                                              @"(@[\w]+[\s]*=|=[\s]*0x|=[\s]*cast[\s]*\()", 
                                              "insert ",                                      
                                              "select ",                                      
                                              "update ",                                     
                                              "delete ",                                        
                                              "drop ",                                         
                                              "alter ",                                         
                                              "sysobjects ",                               
                                              "syscolumns ",                                
                                              " varchar",                                         
                                              " nvarchar",                                         
                                              " char",                             
                                              " nchar",  
                                              " text"};
                foreach (string strInjection in strInjectionArray)
                {
                    if (Regex.IsMatch(queryString, strInjection, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                    {
                        WriteSqlInjectionToTxtFile(queryString);
                        return false;
                    }
                }
            }
            catch { return false; }
            return true;
        }
        //sql post 方式注入过滤    
        private bool ProcessSqlFormStringInjection(string fromString)
        {
            try
            {
                if (fromString.Trim() == "")
                { return true; }
                string[] strInjectionArray = {@"(exec[\s]+(@|sp_executesql)|exec\(|execute[\s]+(@|sp_executesql)|execute\()",   
                                              @"sp_executesql[\s]+[N]{0,1}'",         
                                              @"declare[\s]+@",                              
                                              @"set[\s]+@" };
                foreach (string strInjection in strInjectionArray)
                {
                    if (Regex.IsMatch(fromString, strInjection, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                    {
                        WriteSqlInjectionToTxtFile(fromString);
                        return false;
                    }
                }
            }
            catch { return false; } return true;
        }
        private void WriteSqlInjectionToTxtFile(string sqlInjection)
        {
            try
            {
                using (System.IO.StreamWriter sw = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath("/") + @"\sqlInjection.txt", true, System.Text.Encoding.UTF8))
                {
                    sw.WriteLine(DateTime.Now + "  IP:" + GetClientIP() + "  Url: " + HttpContext.Current.Request.RawUrl + "\r\nInjection:" + sqlInjection); sw.Flush();
                    sw.Close(); sw.Dispose();
                }
            }
            catch { }
        }
        public string GetClientIP()
        {
            string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (null == result || result == String.Empty)
            {
                result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            } if (null == result || result == String.Empty)
            {
                result = HttpContext.Current.Request.UserHostAddress;
            } return result;
        }
    }
}
